#include <iostream>
#include "nocopy.hpp"
#include "Log.hpp"
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cerrno>
#include <cstring>
#include "Thread.hpp"
#include "commd.hpp"
#include "InitAddr.hpp"
using namespace std;

struct ThreadData {
    ThreadData(const int sock, sockaddr_in& server_addr) 
        :_sock(sock)
        ,_server_addr(server_addr)
    {

    }
    int _sock;
    InitAddr _server_addr;
};

// 该线程只负责收消息
void recverRoute(ThreadData& td) {
    char buffer[1024];
    struct sockaddr_in temp;
    socklen_t len = sizeof temp;
    while (true) {
        ssize_t n = recvfrom(td._sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr*)&temp, &len);
        if (n > 0) {
            buffer[n] = '\0';
            InitAddr serveraddr(temp);
            cerr << buffer << endl;
        } else {
            lg.LogMessage(Error, "rever error, errno: %d, strerror: %s", errno, strerror(errno));
        }

    }

}

// 该线程只负责发消息
void senderRoute(ThreadData& td) {
    while (true) {
        string inbuffer;
        cout << "Please Enter# ";
        getline(cin, inbuffer);
        struct sockaddr_in serveraddr = td._server_addr.addr();
        
        ssize_t n = sendto(td._sock, inbuffer.c_str(), inbuffer.size(), 0, (struct sockaddr*)&serveraddr, sizeof serveraddr);
    }
}


void Usage(const string process) {
    cout << "Usage: " << process << "\n\t" << "server_ip server_port\n" << endl;
}

int main(int argc, char* args[]) {
    if (argc != 3) {
        Usage(args[0]);
        return 1;
    }

    string serverip = args[1];
    uint16_t serverport = stoi(args[2]);


    // 客户端就只需要创建套接字即可
    int socketfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socketfd < 0) {
        cerr << "socket err:" << strerror(errno) << endl;
        exit(-1);
    }

    cout << "create socket success socketfd is" << socketfd << endl;  

    // 其实客户端也一定要绑定，但是并不需要我们显示的绑定，系统会自动帮我们绑定
    // 客户端会在首次发送数据的时候自动绑定

    // 填充一下server信息
    struct sockaddr_in server;
    bzero(&server, sizeof server);
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    server.sin_addr.s_addr = inet_addr(serverip.c_str());

    // 创建读写线程
    ThreadData td(socketfd, server);
    thread<ThreadData> recver("recver", recverRoute, td);
    thread<ThreadData> sender("sender", senderRoute, td);
    recver.Start();
    sender.Start();


    // // 客户端发消息
    // while (true) {
    //     string inbuffer;
    //     cout << "Please Enter# ";
    //     getline(cin, inbuffer); // 获取用户输入

    //     // 将信息发给服务器
    //     ssize_t n = sendto(socketfd, inbuffer.c_str(), inbuffer.size(), 0, (struct sockaddr*)&server, sizeof server);
    //     if (n > 0) {
    //         // 收消息
    //         char buffer[1024];
    //         struct sockaddr_in temp;
    //         socklen_t len = sizeof temp;
    //         ssize_t m = recvfrom(socketfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr*)&temp , &len);
    //         if (m > 0) {
    //             buffer[m] = '\0';
    //             cout << "server echo# " << buffer << endl;
    //         } else {
    //             break;
    //         }
    //     } else  {
    //         break;
    //     } 
    // }

    recver.Join();
    sender.Join();

    close(socketfd);
    return 0;
}